home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / vol11n07.zip / BACHTOCC.C < prev    next >
C/C++ Source or Header  |  1992-01-02  |  6KB  |  165 lines

  1. /*---------------------------------------------------
  2.    BACHTOCC.C -- Bach Toccata in D Minor (First Bar)
  3.                  (c) Charles Petzold, 1992
  4.   ---------------------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include <mmsystem.h>
  8.  
  9. #define ID_TIMER    1
  10.  
  11. long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
  12.  
  13. char szAppName[] = "BachTocc" ;
  14.  
  15. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  16.                     LPSTR lpszCmdParam, int nCmdShow)
  17.      {
  18.      HWND        hwnd ;
  19.      MSG         msg ;
  20.      WNDCLASS    wndclass ;
  21.  
  22.      if (!hPrevInstance)
  23.           {
  24.           wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  25.           wndclass.lpfnWndProc   = WndProc ;
  26.           wndclass.cbClsExtra    = 0 ;
  27.           wndclass.cbWndExtra    = 0 ;
  28.           wndclass.hInstance     = hInstance ;
  29.           wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  30.           wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  31.           wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
  32.           wndclass.lpszMenuName  = NULL ;
  33.           wndclass.lpszClassName = szAppName ;
  34.  
  35.           RegisterClass (&wndclass) ;
  36.       }
  37.  
  38.      hwnd = CreateWindow (szAppName, "Bach Toccata in D Minor (First Bar)",
  39.                           WS_OVERLAPPEDWINDOW,
  40.                           CW_USEDEFAULT, CW_USEDEFAULT,
  41.                           CW_USEDEFAULT, CW_USEDEFAULT,
  42.                           NULL, NULL, hInstance, NULL) ;
  43.  
  44.      ShowWindow (hwnd, nCmdShow) ;
  45.      UpdateWindow (hwnd) ;
  46.  
  47.      while (GetMessage (&msg, NULL, 0, 0))
  48.           {
  49.           TranslateMessage (&msg) ;
  50.           DispatchMessage (&msg) ;
  51.           }
  52.      return msg.wParam ;
  53.      }
  54.  
  55. DWORD MidiOutMessage (HMIDIOUT hMidi, int iStatus, int iChannel,
  56.                                      int iData1,  int iData2)
  57.      {
  58.      DWORD dwMessage ;
  59.  
  60.      dwMessage = iStatus | iChannel | (iData1 << 8) | ((long) iData2 << 16) ;
  61.  
  62.      return midiOutShortMsg (hMidi, dwMessage) ;
  63.      }
  64.  
  65. long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  66.      {
  67.      static struct
  68.           {
  69.           int iDur ;
  70.           int iNote [2] ;
  71.           }
  72.           noteseq [] = {
  73.                         110, 69, 81,  110, 67, 79,  990, 69, 81,  220, -1, -1,
  74.                         110, 67, 79,  110, 65, 77,  110, 64, 76,  110, 62, 74,
  75.                         220, 61, 73,  440, 62, 74, 1980, -1, -1,  110, 57, 69,
  76.                         110, 55, 67,  990, 57, 69,  220, -1, -1,  220, 52, 64,
  77.                         220, 53, 65,  220, 49, 61,  440, 50, 62, 1980, -1, -1
  78.                        } ;
  79.  
  80.      static HMIDIOUT hMidiOut ;
  81.      static int      iIndex ;
  82.      int             i ;
  83.  
  84.      switch (message)
  85.           {
  86.           case WM_CREATE:
  87.                if (!SetTimer (hwnd, ID_TIMER, 1000, NULL))
  88.                     {
  89.                     MessageBeep (MB_ICONEXCLAMATION) ;
  90.                     MessageBox (hwnd, "Too many clocks or timers!",
  91.                                 szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  92.  
  93.                     DestroyWindow (hwnd) ;
  94.                     return 0 ;
  95.                     }
  96.  
  97.                if (midiOutOpen (&hMidiOut, MIDIMAPPER, NULL, NULL, 0L))
  98.                     {
  99.                     KillTimer (hwnd, ID_TIMER) ;
  100.  
  101.                     MessageBeep (MB_ICONEXCLAMATION) ;
  102.                     MessageBox (hwnd, "Cannot open MIDI output device!",
  103.                                 szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  104.  
  105.                     DestroyWindow (hwnd) ;
  106.                     return 0 ;
  107.                     }
  108.  
  109.                          // Send Program Change messages for "Church Organ"
  110.  
  111.                MidiOutMessage (hMidiOut, 0xC0,  0, 19, 0) ;
  112.                MidiOutMessage (hMidiOut, 0xC0, 12, 19, 0) ;
  113.  
  114.                return 0 ;
  115.  
  116.           case WM_TIMER:
  117.                          // Loop for 2-note polyphony
  118.  
  119.                for (i = 0 ; i < 2 ; i++)
  120.                     {
  121.                               // Note Off messages for previous note
  122.  
  123.                     if (iIndex != 0 && noteseq[iIndex - 1].iNote[i] != -1)
  124.                          {
  125.                          MidiOutMessage (hMidiOut, 0x80,  0,
  126.                                          noteseq[iIndex - 1].iNote[i], 0) ;
  127.  
  128.                          MidiOutMessage (hMidiOut, 0x80, 12,
  129.                                          noteseq[iIndex - 1].iNote[i], 0) ;
  130.                          }
  131.  
  132.                               // Note On messages for new note
  133.  
  134.                     if (iIndex != sizeof (noteseq) / sizeof (noteseq[0]) &&
  135.                               noteseq[iIndex].iNote[i] != -1)
  136.                          {
  137.                          MidiOutMessage (hMidiOut, 0x90,  0,
  138.                                          noteseq[iIndex].iNote[i], 127) ;
  139.  
  140.                          MidiOutMessage (hMidiOut, 0x90, 12,
  141.                                          noteseq[iIndex].iNote[i], 127) ;
  142.                          }
  143.                     }
  144.  
  145.                if (iIndex != sizeof (noteseq) / sizeof (noteseq[0]))
  146.                     {
  147.                     SetTimer (hwnd, ID_TIMER, noteseq[iIndex++].iDur - 1, NULL);
  148.                     }
  149.                else
  150.                     {
  151.                     midiOutClose (hMidiOut) ;
  152.                     KillTimer (hwnd, ID_TIMER) ;
  153.                     DestroyWindow (hwnd) ;
  154.                     }
  155.  
  156.                return 0 ;
  157.  
  158.           case WM_DESTROY:
  159.                PostQuitMessage (0) ;
  160.                return 0 ;
  161.           }
  162.  
  163.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  164.      }
  165.